home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / sbprolog / v3 / sim.lha / sim / builtin / token.c < prev   
C/C++ Source or Header  |  1991-05-21  |  33KB  |  883 lines

  1. /*  File        : Token.c
  2.     Author      : Richard A. O'Keefe
  3.     Modified by : Deeporn H. Beardsley & Saumya Debray
  4.     Updated     : Summer 1988
  5.     Purpose     : Tokenizer for SB-Prolog.
  6.  
  7. */
  8.  
  9. #ifdef  vms
  10. #include stdio
  11. #else
  12. #include <stdio.h>
  13. #endif
  14.  
  15. /* stuff defined to interface with SB-Prolog */
  16.  
  17. #include "builtin.h"
  18. #include <errno.h>
  19.  
  20. /*  We used to use an 8-bit character set under VMS, but 7-bit ASCII
  21.  *  elsewhere.  Now that DIS 8859/1 exists (a draft international
  22.  *  standard for an 8-bit extension of ASCII) we use that, and we are
  23.  *  in luck: it is almost identical to the VMS character set.
  24.  */
  25. #define AlphabetSize 256
  26. #define SBPMAXINT       268435455
  27.  
  28. extern  char *strcpy(/* CHAR_PTR, CHAR_PTR */);
  29. #define StrCpy(dst, src) (void)strcpy(dst, src)
  30. #define Printf           (void)printf
  31. #define Sprintf          (void)sprintf
  32. #define Fprintf          (void)fprintf
  33.  
  34. #define InRange(X,L,U) ((unsigned)((X)-(L)) <= (unsigned)((U)-(L)))
  35. #define IsLayout(X) InRange(InType(X), SPACE, EOLN)
  36.  
  37. /*  VERY IMPORTANT NOTE: I assume that the stdio library returns the value
  38.  *  EOF when character input hits the end of the file, and that this value
  39.  *  is actually the integer -1.  You will note the DigVal(), InType(), and
  40.  *  OuType() macros below, and there is a ChType() macro used in crack().
  41.  *  They all depend on this assumption.
  42.  */
  43.  
  44. #define DIGIT    0              /* 0 .. 9 */
  45. #define BREAK    1              /* _ */
  46. #define UPPER    2              /* A .. Z */
  47. #define LOWER    3              /* a .. z */
  48. #define SIGN     4              /* -/+*<=>#@$\^&~`:.? */
  49. #define NOBLE    5              /* !; (don't form compounds) */
  50. #define PUNCT    6              /* (),[]|{}% */
  51. #define ATMQT    7              /* ' (atom quote) */
  52. #define LISQT    8              /* " (list quote) */
  53. #define STRQT    9              /* $ (string quote) */
  54. #define CHRQT   10              /* ` (character quote, maybe) */
  55. #define TILDE   11              /* ~ (like character quote but buggy) */
  56. #define SPACE   12              /* layout and control chars */
  57. #define EOLN    13              /* line terminators ^J ^L */
  58. #define REALO   14              /* floating point number */
  59. #define EOFCH   15              /* end of file */
  60. #define ALPHA   DIGIT           /* any of digit, break, upper, lower */
  61. #define BEGIN   BREAK           /* atom left-paren pair */
  62. #define ENDCL   EOLN            /* end of clause token */
  63. #define RREAL    16        /* radix number(real) - overflowed */
  64. #define RDIGIT    17        /* radix number(int) */
  65.  
  66. #define InType(c)  (intab.chtype+1)[c]
  67. #define DigVal(c)  (digval+1)[c]
  68.  
  69. BYTE outqt[EOFCH+1];
  70.  
  71. struct CHARS
  72. {
  73.    int  eolcom;         /* End-of-line comment, default % */
  74.    int  endeol;         /* early terminator of eolcoms, default none */
  75.    int  begcom;         /* In-line comment start, default / */
  76.    int  astcom;         /* In-line comment second, default * */
  77.    int  endcom;         /* In-line comment finish, default / */
  78.    int  radix;          /* Radix character, default ' */
  79.    int  dpoint;         /* Decimal point, default . */
  80.    int  escape;         /* String escape character, default \ */
  81.    int  termin;         /* Terminates a clause */
  82.    CHAR chtype[AlphabetSize+1];
  83. };
  84.  
  85. struct CHARS intab =       /* Special character table */
  86. {
  87.    '%',                    /* eolcom: end of line comments */
  88.    -1,                     /* endeol: early end for eolcoms */
  89.    '/',                    /* begcom: in-line comments */
  90.    '*',                    /* astcom: in-line comments */
  91.    '/',                    /* endcom: in-line comments */
  92.    '\'',                   /* radix : radix separator */
  93.    '.',                    /* dpoint: decimal point */
  94.    -1,                     /* escape: string escape character */
  95.    '.',                    /* termin: ends clause, sign or solo */
  96.    {
  97.        EOFCH,                  /* really the -1th element of the table: */
  98.    /*  ^@      ^A      ^B      ^C      ^D      ^E      ^F      ^G      */
  99.        SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
  100.    /*  ^H      ^I      ^J      ^K      ^L      ^M      ^N      ^O      */
  101.        SPACE,  SPACE,  EOLN,   SPACE,  EOLN,   SPACE,  SPACE,  SPACE,
  102.    /*  ^P      ^Q      ^R      ^S      ^T      ^U      ^V      ^W      */
  103.        SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
  104.    /*  ^X      ^Y      ^Z      ^[      ^\      ^]      ^^      ^_      */
  105.        SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
  106.    /*  sp      !       "       #       $       %       &       '       */
  107.        SPACE,  NOBLE,  LISQT,  SIGN,   LOWER,  PUNCT,  SIGN,   ATMQT,
  108.    /*  (       )       *       +       ,       -       .       /       */
  109.        PUNCT,  PUNCT,  SIGN,   SIGN,   PUNCT,  SIGN,   SIGN,   SIGN,
  110.    /*  0       1       2       3       4       5       6       7       */
  111.        DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,
  112.    /*  8       9       :       ;       <       =       >       ?       */
  113.        DIGIT,  DIGIT,  SIGN,   PUNCT,  SIGN,   SIGN,   SIGN,   SIGN,
  114.    /*  @       A       B       C       D       E       F       G       */
  115.        SIGN,   UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,
  116.    /*  H       I       J       K       L       M       N       O       */
  117.        UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,
  118.    /*  P       Q       R       S       T       U       V       W       */
  119.        UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,
  120.    /*  X       Y       Z       [       \       ]       ^       _       */
  121.        UPPER,  UPPER,  UPPER,  PUNCT,  SIGN,   PUNCT,  SIGN,   BREAK,
  122.    /*  `       a       b       c       d       e       f       g       */
  123.        SIGN,   LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,
  124.    /*  h       i       j       k       l       m       n       o       */
  125.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,
  126.    /*  p       q       r       s       t       u       v       w       */
  127.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,
  128.    /*  x       y       z       {       |       }       ~       ^?      */
  129.        LOWER,  LOWER,  LOWER,  PUNCT,  PUNCT,  PUNCT,  SIGN,   SPACE,
  130.    /*  128     129     130     131     132     133     134     135     */
  131.        SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
  132.    /*  136     137     138     139     140     141     142     143     */
  133.        SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
  134.    /*  144     145     146     147     148     149     150     151     */
  135.        SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
  136.    /*  152     153     154     155     156     157     158     159     */
  137.        SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
  138.    /*  NBSP    !-inv   cents   pounds  ching   yen     brobar  section */
  139.        SPACE,  SIGN,   SIGN,   SIGN,   SIGN,   SIGN,   SIGN,   SIGN,
  140.    /*  "accent copyr   -a ord  <<      nothook SHY     (reg)   ovbar   */
  141.        SIGN,   SIGN,   LOWER,  SIGN,   SIGN,   SIGN,   SIGN,   SIGN,
  142.    /*  degrees +/-     super 2 super 3 -       micron  pilcrow -       */
  143.        SIGN,   SIGN,   LOWER,  LOWER,  SIGN,   SIGN,   SIGN,   SIGN,
  144.    /*  ,       super 1 -o ord  >>      1/4     1/2     3/4     ?-inv   */
  145.        SIGN,   LOWER,  LOWER,  SIGN,   SIGN,   SIGN,   SIGN,   SIGN,
  146.    /*  `A      'A      ^A      ~A      "A      oA      AE      ,C      */
  147.        UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,
  148.    /*  `E      'E      ^E      "E      `I      'I      ^I      "I      */
  149.        UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,
  150.    /*  ETH     ~N      `O      'O      ^O      ~O      "O      x times */
  151. #ifdef  vms
  152.        UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,
  153. #else
  154.        UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  SIGN,
  155. #endif
  156.    /*  /O      `U      'U      ^U      "U      'Y      THORN   ,B      */
  157.        UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  UPPER,  LOWER,
  158.    /*  `a      'a      ^a      ~a      "a      oa      ae      ,c      */
  159.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,
  160.    /*  `e      'e      ^e      "e      `i      'i      ^i      "i      */
  161.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,
  162.    /*  eth     ~n      `o      'o      ^o      ~o      "o      -:-     */
  163. #ifdef  vms
  164.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,
  165. #else
  166.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  SIGN,
  167. #endif
  168.    /*  /o      `u      'u      ^u      "u      'y      thorn  "y       */
  169. #ifdef  vms
  170.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  SPACE
  171. #else
  172.        LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER,  LOWER
  173. #endif
  174.    }
  175. };
  176.  
  177. CHAR digval[AlphabetSize+1] =
  178. {
  179.         99,                     /* really the -1th element of the table */
  180.     /*  ^@      ^A      ^B      ^C      ^D      ^E      ^F      ^G      */
  181.         99,     99,     99,     99,     99,     99,     99,     99,
  182.     /*  ^H      ^I      ^J      ^K      ^L      ^M      ^N      ^O      */
  183.         99,     99,     99,     99,     99,     99,     99,     99,
  184.     /*  ^P      ^Q      ^R      ^S      ^T      ^U      ^V      ^W      */
  185.         99,     99,     99,     99,     99,     99,     99,     99,
  186.     /*  ^X      ^Y      ^Z      ^[      ^\      ^]      ^^      ^_      */
  187.         99,     99,     99,     99,     99,     99,     99,     99,
  188.     /*  sp      !       "       #       $       %       &       '       */
  189.         99,     99,     99,     99,     99,     99,     99,     99,
  190.     /*  (       )       *       +       ,       -       .       /       */
  191.         99,     99,     99,     99,     99,     99,     99,     99,
  192.     /*  0       1       2       3       4       5       6       7       */
  193.         0,      1,      2,      3,      4,      5,      6,      7,
  194.     /*  8       9       :       ;       <       =       >       ?       */
  195.         8,      9,      99,     99,     99,     99,     99,     99,
  196.     /*  @       A       B       C       D       E       F       G       */
  197.         99,     10,     11,     12,     13,     14,     15,     99,
  198.     /*  H       I       J       K       L       M       N       O       */
  199.         99,     99,     99,     99,     99,     99,     99,     99,
  200.     /*  P       Q       R       S       T       U       V       W       */
  201.         99,     99,     99,     99,     99,     99,     99,     99,
  202.     /*  X       Y       Z       [       \       ]       ^       _       */
  203.         99,     99,     99,     99,     99,     99,     99,     0,  /*NB*/
  204.     /*  `       a       b       c       d       e       f       g       */
  205.         99,     10,     11,     12,     13,     14,     15,     99,
  206.     /*  h       i       j       k       l       m       n       o       */
  207.         99,     99,     99,     99,     99,     99,     99,     99,
  208.     /*  p       q       r       s       t       u       v       w       */
  209.         99,     99,     99,     99,     99,     99,     99,     99,
  210.     /*  x       y       z       {       |       }       ~       ^?      */
  211.         99,     99,     99,     99,     99,     99,     99,     99,
  212.     /*  128     129     130     131     132     133     134     135     */
  213.         99,     99,     99,     99,     99,     99,     99,     99,
  214.     /*  136     137     138     139     140     141     142     143     */
  215.         99,     99,     99,     99,     99,     99,     99,     99,
  216.     /*  144     145     146     147     148     149     150     151     */
  217.         99,     99,     99,     99,     99,     99,     99,     99,
  218.     /*  152     153     154     155     156     157     158     159     */
  219.         99,     99,     99,     99,     99,     99,     99,     99,
  220.     /*  160     161     162     163     164     165     166     167     */
  221.         99,     99,     99,     99,     99,     99,     99,     99,
  222.     /*  168     169     170(-a) 171     172     173     174     175     */
  223.         99,     99,     99,     99,     99,     99,     99,     99,
  224.     /*  176     177     178(2)  179(3)  180     181     182     183     */
  225.         99,     99,     2,      3,      99,     99,     99,     99,
  226.     /*  184     185(1)  186(-o) 187     188     189     190     191     */
  227.         99,     1,      99,     99,     99,     99,     99,     99,
  228.     /*  192     193     194     195     196     197     198     199     */
  229.         99,     99,     99,     99,     99,     99,     99,     99,
  230.     /*  200     201     202     203     204     205     206     207     */
  231.         99,     99,     99,     99,     99,     99,     99,     99,
  232.     /*  208     209     210     211     212     213     214     215     */
  233.         99,     99,     99,     99,     99,     99,     99,     99,
  234.     /*  216     217     218     219     220     221     222     223     */
  235.         99,     99,     99,     99,     99,     99,     99,     99,
  236.     /*  224     225     226     227     228     229     230     231     */
  237.         99,     99,     99,     99,     99,     99,     99,     99,
  238.     /*  232     233     234     235     236     237     238     239     */
  239.         99,     99,     99,     99,     99,     99,     99,     99,
  240.     /*  240     241     242     243     244     245     246     247     */
  241.         99,     99,     99,     99,     99,     99,     99,     99,
  242.     /*  248     249     250     251     252     253     254     255     */
  243.         99,     999,     99,     99,     99,     99,     99,     99
  244.     };
  245.  
  246.  
  247. /* values returned to calling program */
  248.  
  249. #define SPECIAL 0       /* puncuation , ( ) [ ] ... */
  250. #define VARO    1       /* type is a variable */
  251. #define FUNC    2    /* type is atom( */
  252. #define NUMBERO 3       /* type is a number */
  253. #define ATOMO   4       /* type is an atom */
  254. #define ENDCLS    5       /* END of clause but not file */
  255. #define USCORE  6       /* underscore '_' */
  256. #define SEMI    7    /* ; */
  257. #define BADEND  8       /* END of file, not end of clause */
  258. #define STRING  9       /* type is a char string */
  259.  
  260. int cNUMERO = 0, cATOMO   = 0, cFUNC = 0, cVARO   = 0, cUSCORE = 0,
  261.     cSTRING = 0, cSPECIAL = 0, cSEMI = 0, cENDCLS = 0, cENDPRG = 0;
  262.  
  263. extern LONG_PTR insert();
  264. static BYTE perm = PERM;
  265.  
  266. extern FILE *curr_in, *curr_out;    /* current input, output streams */
  267.  
  268.  
  269. void SyntaxError(message)
  270. CHAR_PTR message;
  271. {
  272.    Fprintf(stderr, "Syntax error: %s\n", message);
  273.    exit(1);
  274. }
  275.  
  276. /*  GetToken() reads a single token from the input stream and returns
  277.  *  its type, which is one of
  278.  *      DIGIT   -- a number
  279.  *      BEGIN   -- an atom( pair
  280.  *      LOWER   -- an atom
  281.  *      UPPER   -- a variable
  282.  *      PUNCT   -- a single punctuation mark
  283.  *      LISQT   -- a quoted list of character codes
  284.  *      STRQT   -- a quoted string
  285.  *      ENDCL   -- end of clause (normally '.\n').
  286.  *      EOFCH   -- signifies end-of-file.
  287.  *      RREAL   -- a real, from some radix notation, in double_v.
  288.  *      RDIGIT  -- an integer, from some radix notation, in rad_int.
  289.  *  In all cases except the last, the text of the token is in AtomStr.
  290.  *  There are two questions: between which pairs of adjacent tokens is
  291.  *  a space (a) necessary, (b) desirable?  There is an additional
  292.  *  dummy token type used by the output routines, namely
  293.  *      NOBLE   -- extra space is definitely not needed.
  294.  *  I leave it as an exercise for the reader to answer question (a).
  295.  *  Since this program is to produce output I find palatable (even if
  296.  *  it isn't exactly what I'd write myself), extra spaces are ok.  In
  297.  *  fact, the main use of this program is as an editor command, so it
  298.  *  is normal to do a bit of manual post-processing.  Question (b) is
  299.  *  the one to worry about then.  My answer is that a space is never
  300.  *  written
  301.  *      - after  PUNCT ( [ { |
  302.  *      - before PUNCT ) ] } | , <ENDCL>
  303.  *  is written after comma only sometimes, and is otherwise always
  304.  *  written.  The variable lastput thus takes these values:
  305.  *      ALPHA   -- put a space except before PUNCT
  306.  *      SIGN    -- as alpha, but different so ENDCL knows to put a space.
  307.  *      NOBLE   -- don't put a space
  308.  *      ENDCL   -- just ended a clause
  309.  *      EOFCH   -- at beginning of file
  310.  */
  311.  
  312. int     lastc = ' ';    /* previous character */
  313. #define MaxStrLen      1000 
  314. BYTE    AtomStr[MaxStrLen+20];
  315. LONG    list_p;
  316. int     rtnint;
  317. double  double_v;
  318. LONG    rad_int;
  319.  
  320. CHAR    tok2long[] = "token too long";
  321. CHAR    eofinrem[] = "end of file in comment";
  322. CHAR    badexpt[]  = "bad exponent";
  323. CHAR    badradix[] = "radix > 36";
  324.  
  325.  
  326. /*  read_character(FILE* card, BYTE q)
  327.  *  reads one character from a quoted atom, list, string, or character.
  328.  *  Doubled quotes are read as single characters, otherwise a
  329.  *  quote is returned as -1 and lastc is set to the next character.
  330.  *  If the input syntax has character escapes, they are processed.
  331.  *  Note that many more character escape sequences are accepted than
  332.  *  are generated.  There is a divergence from C: \xhh sequences are
  333.  *  two hexadecimal digits long, not three.
  334.  *  Note that the \c and \<space> sequences combine to make a pretty
  335.  *  way of continuing strings.  Do it like this:
  336.  *      "This is a string, which \c
  337.  *     \ has to be continued over \c
  338.  *     \ several lines.\n".
  339.  */
  340.  
  341. int read_character(card, q)
  342. register FILE *card;
  343. register int q;
  344. {
  345.    register int c;
  346.  
  347.    c = getc(card);
  348. BACK:
  349.    if (c < 0) {
  350. DOERR:
  351.       if (q < 0)
  352.          SyntaxError("end of file in character constant");
  353.       else {
  354.          CHAR message[80];
  355.          Sprintf(message, "end of file in %cquoted%c constant", q, q);
  356.          SyntaxError(message);
  357.       }
  358.    }
  359.    if (c == q) {
  360.       c = getc(card);
  361.       if (c == q)
  362.      return c;
  363.       lastc = c;
  364.       return -1;
  365.    } else if (c != intab.escape)
  366.       return c;
  367.  
  368.    /*  If we get here, we have read the "\" of an escape sequence  */
  369.  
  370.    c = getc(card);
  371.    switch (c) {
  372.       case EOF:
  373.      clearerr(curr_in);
  374.      goto DOERR;
  375.       case 'n':  case 'N':         /* newline */
  376.          return 10;
  377.       case 't':  case 'T':         /* tab */
  378.          return  9;
  379.       case 'r':  case 'R':         /* reeturn */
  380.          return 13;
  381.       case 'v':  case 'V':         /* vertical tab */
  382.          return 11;
  383.       case 'b':  case 'B':         /* backspace */
  384.          return  8;
  385.       case 'f':  case 'F':         /* formfeed */
  386.          return 12;
  387.       case 'e':  case 'E':         /* escape */
  388.          return 27;
  389.       case 'd':  case 'D':         /* delete */
  390.          return 127;
  391.       case 's':  case 'S':         /* space */
  392.          return 32;
  393.       case 'a':  case 'A':         /* alarm */
  394.          return  7;
  395.       case '^':                    /* control */
  396.          c = getc(card);
  397.          if (c < 0)
  398.         goto DOERR;
  399.          return (c == '?' ? 127 : c&31);
  400.       case 'c':  case 'C':         /* continuation */
  401.          while (IsLayout(c = getc(card))) 
  402.         ;
  403.          goto BACK;
  404.       case 'x':  case 'X':         /* hexadecimal */
  405.          {  int i, n;
  406.             for (n = 0, i = 2; --i >= 0; n = (n<<4) + DigVal(c))
  407.                if (DigVal(c = getc(card)) >= 16) {
  408.                   if (c < 0)
  409.                  goto DOERR;
  410.                   (void)ungetc(c, card);
  411.                   break;
  412.                }
  413.             return (n & 255);
  414.          }
  415.       case 'o':  case 'O':         /* octal */
  416.          c = getc(card);
  417.          if (DigVal(c) >= 8) {
  418.             if (c < 0)
  419.            goto DOERR;
  420.             (void)ungetc(c, card);
  421.             return 0;
  422.          }
  423.       case '0':  case '1':  case '2':  case '3':
  424.       case '4':  case '5':  case '6':  case '7':
  425.          {  int i, n;
  426.             for (n = c-'0', i = 2; --i >= 0; n = (n<<3) + DigVal(c))
  427.                if (DigVal(c = getc(card)) >= 8) {
  428.                   if (c < 0)
  429.                  goto DOERR;
  430.                   (void)ungetc(c, card);
  431.                   break;
  432.                }
  433.             return (n & 255);
  434.          }
  435.       default:
  436.          if (!IsLayout(c))
  437.         return c;
  438.          c = getc(card);
  439.          goto BACK;
  440.    }
  441.  
  442.  
  443. /*  com0plain(card, endeol)
  444.  *  These comments have the form
  445.  *      <eolcom> <char>* <newline>                      {PUNCT}
  446.  *  or  <eolcom><eolcom> <char>* <newline>              {SIGN }
  447.  *  depending on the classification of <eolcom>.  Note that we could
  448.  *  handle ADA comments with no trouble at all.  There was a Pop-2
  449.  *  dialect which had end-of-line comments using "!" where the comment
  450.  *  could also be terminated by "!".  You could obtain the effect of
  451.  *  including a "!" in the comment by doubling it, but what you had
  452.  *  then was of course two comments.  The endeol parameter of this
  453.  *  function allows the handling of comments like that which can be
  454.  *  terminated either by a new-line character or an <endeol>, whichever
  455.  *  comes first.  For ordinary purposes, endeol = -1 will do fine.
  456.  *  When this is called, the initial <eolcom>s have been consumed.
  457.  *  We return the first character after the comment.
  458.  *  If the end of the source file is encountered, we do not treat it
  459.  *  as an error, but quietly close the comment and return EOF as the
  460.  *  "FOLLOWing" character.
  461.  */
  462.  
  463. int com0plain(card, endeol)
  464. register FILE *card;        /* source file */
  465. register int endeol;        /* The closing character "!" */
  466. {
  467.    register int c;
  468.  
  469.    while ((c = getc(card)) >= 0 && c != '\n' && c != endeol)
  470.       ;
  471.    if (c >= 0)
  472.       c = getc(card);
  473.    return c;
  474. }
  475.  
  476.  
  477. /*  The states in the next two functions are
  478.  *      0       - after an uninteresting character
  479.  *      1       - after an "astcom"
  480.  *      2       - after a  "begcom"
  481.  *  Assuming begcom = "(", astom = "#", endcom = ")",
  482.  *  com2plain will accept "(#)" as a complete comment.  This can
  483.  *  be changed by initialising the state to 0 rather than 1.
  484.  *  The same is true of com2nest, which accepts "(#(#)#) as a
  485.  *  complete comment.  Changing it would be rather harder.
  486.  *  Fixing the bug where the closing <astcom> is copied if it is
  487.  *  not an asterisk may entail rejecting "(#)".
  488.  */
  489.  
  490. /*  com2plain(card, astcom, endcom)
  491.  *  handles PL/I-style comments, that is, comments which begin with
  492.  *  a pair of characters <begcom><astcom> and end with a pair of
  493.  *  chracters <astcom><endcom>, where nesting is not allowed.  For
  494.  *  example, if we take begcom='(', astcom='*', endcom=')' as in
  495.  *  Pascal, the comment "(* not a (* plain *)^ comment *) ends at
  496.  *  the "^".
  497.  *  For this kind of comment, it is perfectly sensible for any of
  498.  *  the characters to be equal.  For example, if all three of the
  499.  *  bracket characters are "#", then "## stuff ##" is a comment.
  500.  *  When this is called, the initial <begcom><astcom> has been consumed.
  501.  */
  502.  
  503. void com2plain(card, astcom, endcom)
  504. register FILE *card;        /* source file */
  505. int astcom;                 /* The asterisk character "*" */
  506. int endcom;                 /* The closing character "/" */
  507. {
  508.    register int c;
  509.    register int state;
  510.  
  511.    for (state = 0; (c = getc(card)) >= 0; ) {
  512.       if (c == endcom && state)
  513.      break;
  514.       state = c == astcom;
  515.    }
  516.    if (c < 0)
  517.       SyntaxError(eofinrem);
  518. }
  519.  
  520.  
  521. int GetToken()
  522. {
  523.    register FILE *card = curr_in;
  524.    register BYTE_PTR s = AtomStr;
  525.    register int  c, d;
  526.    register int  n = MaxStrLen;
  527.    LONG     oldv = 0, newv = 0; 
  528.    LONG_PTR newpair, list_head, stack_top;
  529.  
  530.    c = lastc;
  531. START:
  532.    switch (InType(c)) {
  533.       case DIGIT:
  534.          /* The FOLLOWing kinds of numbers exist:
  535.           * (1) unsigned decimal integers: d+
  536.           * (2) unsigned based integers: d+Ro+[R]
  537.           * (3) unsigned floats: d* [. d*] [e +/-] d+
  538.           * (4) characters: 0Rc[R]
  539.           * We allow underscores in numbers too, ignoring them.
  540.           */
  541.          do {
  542.             if (c != '_')
  543.            *s++ = c;
  544.             c = getc(card);
  545.          } while (InType(c) <= BREAK);
  546.          if (c == intab.radix) { 
  547.             *s = 0;
  548.             for (d = 0, s = AtomStr; c = *s++; ) {
  549.                d = d*10-'0'+c;
  550.                if (d > 36)
  551.           SyntaxError(badradix);
  552.             }
  553.             if (d == 0) {       /*  0'c['] is a character code  */
  554.                d = read_character(card, -1);
  555.                Sprintf(AtomStr, "%d", d);
  556.                d = getc(card);
  557.                lastc = d == intab.radix ? getc(card) : d;
  558.                return DIGIT;
  559.             }
  560.             while (c = getc(card), DigVal(c) < 99)
  561.                if (c != '_') {
  562.           oldv = newv;
  563.           newv = newv*d + DigVal(c);
  564.           if (newv < oldv || newv > SBPMAXINT) {
  565.              Fprintf(stderr, "*** overflow in radix notation ***\n");
  566.              double_v = oldv*1.0*d + DigVal(c);
  567.              while (c = getc(card), DigVal(c) < 99)
  568.                         if (c != '_') 
  569.                double_v = double_v*d + DigVal(c);
  570.                      if (c == intab.radix)
  571.                 c = getc(card);
  572.                      lastc = c;
  573.              return RREAL;
  574.           }
  575.            }
  576. /*
  577.             Sprintf(AtomStr, "%ld", newv);
  578. */
  579.         rad_int = newv;
  580.             if (c == intab.radix)
  581.            c = getc(card);
  582.             lastc = c;
  583.             return RDIGIT;
  584.          } else if (c == intab.dpoint) {
  585.             d = getc(card);
  586.             if (InType(d) == DIGIT) {
  587. DECIMAL:       *s++ = '.';
  588.                do {
  589.                   if (d != '_')
  590.              *s++ = d;
  591.                   d = getc(card);
  592.                } while (InType(d) <= BREAK);
  593.                if ((d | 32) == 'e') {
  594.                   *s++ = 'E';
  595.                   d = getc(card);
  596.                   if (d == '-') {
  597.              *s++ = d;
  598.              d = getc(card);
  599.           } else if (d == '+')
  600.              d = getc(card);
  601.                   if (InType(d) > BREAK)
  602.              SyntaxError(badexpt);
  603.                   do {
  604.                      if (d != '_')
  605.                 *s++ = d;
  606.                      d = getc(card);
  607.                   } while (InType(d) <= BREAK);
  608.                }
  609.                c = d;
  610.                *s = 0;
  611.            lastc = c;
  612.                return REALO;
  613.             } else       /* c has not changed */
  614.                ungetc(d, card);
  615.          }
  616.          *s = 0;
  617.      lastc = c;
  618.          return DIGIT;
  619.  
  620.       case BREAK:
  621.       case UPPER:
  622.          do {
  623.             if (--n < 0)
  624.            SyntaxError(tok2long);
  625.             *s++ = c;
  626.         c = getc(card);
  627.          } while (InType(c) <= LOWER);
  628.          *s = 0;
  629.      lastc = c;
  630.          rtnint = (int)(s - AtomStr);
  631.          return UPPER;
  632.  
  633.       case LOWER:
  634.           do {
  635.              if (--n < 0) SyntaxError(tok2long);
  636.              *s++ = c;
  637.          c = getc(card);
  638.           } while (InType(c) <= LOWER);
  639.           *s = 0;
  640. SYMBOL:   if (c == '(') {
  641.              lastc = getc(card);
  642.              rtnint = (int)(s - AtomStr);
  643.              return BEGIN;
  644.           } else {
  645.              lastc = c;
  646.              rtnint = (int)(s - AtomStr);
  647.              return LOWER;
  648.           }
  649.  
  650.       case SIGN:
  651.           *s = c;
  652.       d = getc(card);
  653.           if (c == intab.begcom && d == intab.astcom) {
  654. ASTCOM:      com2plain(card, d, intab.endcom);
  655.              c = getc(card);
  656.              goto START;
  657.           } else if (c == intab.dpoint && InType(d) == DIGIT) {
  658.              *s++ = '0';
  659.              goto DECIMAL;
  660.           }
  661.           while (InType(d) == SIGN) {
  662.              if (--n == 0)
  663.         SyntaxError(tok2long);
  664.              *++s = d;
  665.          d = getc(card);
  666.           }
  667.           *++s = 0;
  668.           if (InType(d) >= SPACE && c == intab.termin && AtomStr[1] == 0) {
  669.              lastc = d;
  670.              return ENDCL;       /* i.e. '.' FOLLOWed by layout */
  671.           }
  672.           c = d;
  673.           goto SYMBOL;
  674.  
  675.       case NOBLE:
  676.           if (c == intab.termin) {
  677.              *s = 0;
  678.          lastc = ' ';
  679.              return ENDCL;
  680.           } else if (c == intab.eolcom) {
  681.              c = com0plain(card, intab.endeol);
  682.              goto START;
  683.           }
  684.           *s++ = c;
  685.       *s = 0;
  686.           lastc = c = getc(card);
  687.           goto SYMBOL;
  688.  
  689.       case PUNCT:
  690.          if (c == intab.termin) {
  691.             *s = 0;
  692.         lastc = ' ';
  693.             return ENDCL;
  694.          } else if (c == intab.eolcom) {
  695.             c = com0plain(card, intab.endeol);
  696.             goto START;
  697.          }
  698.          d = getc(card);
  699.          if (c == intab.begcom && d == intab.astcom)
  700.         goto ASTCOM;
  701.  
  702.          /*  If we arrive here, c is an ordinary punctuation mark  */
  703.  
  704.          if (c == '(')    /* need to distingusih between atom( and atom ( */
  705.             *s++ = ' ';
  706.          lastc = d;
  707.      *s++ = c;
  708.      *s = 0;
  709.          rtnint = (int)(s - AtomStr);
  710.          return PUNCT;
  711.  
  712.       case CHRQT:
  713.          /* `c[`] is read as an integer.
  714.            * Eventually we should treat characters as a distinct
  715.            * token type, so they can be generated on output.
  716.            * If the character quote, atom quote, list quote,
  717.            * or string quote is the radix character, we should
  718.            * generate 0'x notation, otherwise `x`.
  719.            */
  720.          d = read_character(card, -1);
  721.          Sprintf(AtomStr, "%d", d);
  722.          d = getc(card);
  723.          lastc = d == c ? getc(card) : d;
  724.          return DIGIT;
  725.  
  726.       case ATMQT:
  727.       case STRQT:
  728.          while ((d = read_character(card, c)) >= 0) {
  729.             if (--n < 0) SyntaxError(tok2long);
  730.             *s++ = d;
  731.          }
  732.          *s = 0;
  733.          rtnint = (int) (s - AtomStr);
  734.          c = lastc;
  735.          goto SYMBOL;
  736.  
  737.       case LISQT: 
  738.      /* check for potential heap overflow */
  739.      /*   (this will guarantee space for lists of up to 50 elements) */
  740.      stack_top = (breg < ereg) ? breg : ereg - ENV_SIZE(cpreg);
  741.      if (stack_top < hreg + 100) {
  742.         /* garbage_collection("GetToken"); */
  743.         if (stack_top < hreg + 100)    /* still too full */
  744.            quit("Heap overflow\n");
  745.      }
  746.  
  747.      list_head = newpair = hreg;
  748.          while ((d = read_character(card, c)) >= 0) {
  749.         hreg += 2;
  750.         *newpair++ = MAKEINT(d);
  751.         *newpair++ = (LONG)hreg | LIST_TAG; 
  752.      }
  753.      if (list_head == hreg)   /* null string */
  754.         list_p = nil_sym;
  755.      else {
  756.         *(--newpair) = nil_sym;
  757.         list_p = (LONG)list_head | LIST_TAG;
  758.      }
  759.      return LISQT;
  760.  
  761.       case EOLN:
  762.       case SPACE:
  763.          c = getc(card);
  764.          goto START;
  765.  
  766.       case EOFCH:
  767.      clearerr(curr_in);
  768.          return EOFCH;
  769.    }
  770.    Fprintf(stderr, "Internal error: InType(%d)==%d\n", c, InType(c));
  771.    abort();                /* There is no way we can get here */
  772.    /*NOTREACHED*/
  773. }
  774.  
  775.  
  776. void b_NEXT_TOKEN()
  777. {
  778.    register LONG     op;
  779.    register LONG_PTR top;
  780.    register FILE     *card = curr_in;
  781.    int      i, atoi(), oldnum, newnum;
  782.    int      len;
  783.    double   atof();
  784.    LONG     makefloat(), ptr;
  785.  
  786.    i = GetToken();
  787.    switch (i) {
  788.       case LOWER:
  789.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(ATOMO);
  790.          ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG;
  791.      op = reg[2];  DEREF(op);  FOLLOW(op) = ptr;
  792. cATOMO++;
  793.          break;
  794.       case BEGIN:
  795.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(FUNC);
  796.          ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG;
  797.      op = reg[2];  DEREF(op);  FOLLOW(op) = ptr;
  798. cFUNC++;
  799.          break;
  800.       case UPPER:
  801.          if (AtomStr[0] == '_' && AtomStr[1] == 0) {
  802.         op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(USCORE);
  803. cUSCORE++;
  804.          } else {
  805.         op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(VARO);
  806. cVARO++;
  807.      }
  808.      if (rtnint > 256) {
  809.         AtomStr[256] = 0;
  810.         rtnint = 256;
  811.         Fprintf(stderr, "*** Name of constant too long: %s\n", AtomStr);
  812.          }
  813.      ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG;
  814.      op = reg[2];  DEREF(op);  FOLLOW(op) = ptr;
  815.          break;
  816.       case REALO:
  817.      op = reg[2];  DEREF(op);
  818.      FOLLOW(op) = makefloat(atof(AtomStr));
  819.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(NUMBERO);
  820. cNUMERO++;
  821.          break;
  822.       case RREAL:
  823.      op = reg[2];  DEREF(op);  FOLLOW(op) = makefloat(double_v);
  824.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(NUMBERO);
  825. cNUMERO++;
  826.      break;
  827.       case RDIGIT:
  828. cNUMERO++;
  829.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(NUMBERO);
  830.      op = reg[2];  DEREF(op);  FOLLOW(op) = MAKEINT(rad_int);
  831.      break;
  832.       case DIGIT:
  833. cNUMERO++;
  834.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(NUMBERO);
  835.      op = reg[2];  DEREF(op); 
  836.      for (len = oldnum = newnum = 0; AtomStr[len] != 0; len++) {
  837.               oldnum = newnum;
  838.             newnum = newnum * 10 + DigVal(AtomStr[len]);
  839.             if (newnum < oldnum || newnum > SBPMAXINT) {
  840.            Fprintf(stderr, "*** overflow >> %s\n", AtomStr);
  841.            len = strlen(AtomStr);
  842.            AtomStr[len++] = '.';    
  843.            AtomStr[len++] = '0';
  844.            AtomStr[len] = 0;
  845.            FOLLOW(op) = makefloat(atof(AtomStr));
  846.            return;
  847.         }
  848.      }
  849.           FOLLOW(op) = MAKEINT(newnum);
  850.          break;
  851.       case LISQT:
  852.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(STRING);
  853.      op = reg[2];  DEREF(op);  FOLLOW(op) = list_p;
  854. cSTRING++;
  855.          break;
  856.       case PUNCT:
  857.          /* there are nine punctuation marks, */
  858.          /* ( , )  [ | ]  { ; }  */
  859.          /* % is listed as one, but isn't really. */
  860.          if (AtomStr[0] == ';') {
  861.         op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(SEMI);
  862. cSEMI++;
  863.          } else {
  864.         op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(SPECIAL);
  865. cSPECIAL++;
  866.             ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG;
  867.         op = reg[2];  DEREF(op);  FOLLOW(op) = ptr;
  868.          }
  869.          break;
  870.       case ENDCL:
  871.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(ENDCLS);
  872. cENDCLS++;
  873.          break;
  874.       case EOFCH:
  875.      op = reg[1];  DEREF(op);  FOLLOW(op) = MAKEINT(BADEND);
  876.          break;
  877.       default:
  878.          Fprintf(stderr, "Internal error %d %s\n", i, AtomStr);
  879.    }
  880. }
  881.  
  882.